package sk.tuke.serviceDao;

import org.hibernate.ObjectNotFoundException;
import org.hibernate.Query;
import org.hibernate.Session;

import sk.tuke.persistance.AddressPo;
import sk.tuke.persistance.DepartmentPo;
import sk.tuke.persistance.DoctorPo;
import sk.tuke.persistance.InsurancePo;
import sk.tuke.persistance.PatientPo;
import sk.tuke.persistance.PhonePo;
import sk.tuke.persistance.UserPo;
import java.security.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class UserManagementDao extends AbstractDao {

	public DoctorPo createDoctor(String firstname, String middlename, String lastname, List<AddressPo> addresses, String personalId, String password,
			String email, List<PhonePo> phones, String salutation, InsurancePo insurancePo, DepartmentPo departmentPo) throws Exception {
		Session session = getSession();
		session.beginTransaction();

		DoctorPo doctor = new DoctorPo();

		for (PhonePo phonePo : phones) {
			phonePo.setUser(doctor);
		}

		for (AddressPo addressPo : addresses) {
			addressPo.setUser(doctor);
		}
		doctor.setSalutation(salutation);
		doctor.setFirstname(firstname);
		doctor.setLastname(lastname);
		doctor.setMiddlename(middlename);
		doctor.setAddress(addresses);
		doctor.setPhone(phones);
		doctor.setEmail(email);
		doctor.setNumber(personalId);
		doctor.setInsurance(insurancePo);
		doctor.setDepartment(departmentPo);

		if (password == null)
			password = UUID.randomUUID().toString();
		doctor.setPassword(generatePassword(password));

		session.save(doctor);
		session.getTransaction().commit();
		session.close();
		return doctor;
	}

	public DoctorPo updateDoctor(Integer existing, String firstname, String middlename, String lastname, List<AddressPo> addresses, String personalId,
			String password, String email, List<PhonePo> phones, String salutation, Integer insuranceNumber) throws NoSuchAlgorithmException {

		DoctorPo doctor = (DoctorPo) getDoctors(existing);

		doctor.setSalutation(salutation);
		doctor.setFirstname(firstname);
		doctor.setLastname(lastname);
		doctor.setMiddlename(middlename);
		doctor.setAddress(addresses);
		doctor.setPhone(phones);
		doctor.setEmail(email);
		doctor.setNumber(personalId);

		if (password == null)
			password = UUID.randomUUID().toString();
		doctor.setPassword(generatePassword(password));

		Session session = getSession();
		Query query = session.createQuery("FROM InsurancePo where number = :insuranceNumber");
		query.setLong("insuranceNumber", insuranceNumber);
		InsurancePo insurance = (InsurancePo) query.uniqueResult();
		doctor.setInsurance(insurance);

		session.save(doctor);
		session.getTransaction().commit();
		session.close();
		return doctor;
	}

	@SuppressWarnings("unchecked")
	public List<DoctorPo> getDoctors(Integer number) {
		Session session = getSession();
		Query query;
		List<DoctorPo> doctorPos = new ArrayList<DoctorPo>();
		if (number == null) {
			query = session.createQuery("select u from DoctorPo u");
		} else {
			query = session.createQuery("select u from DoctorPo u where number =  :number");
			query.setInteger("number", number);
		}
		doctorPos.addAll(query.list());
		return doctorPos;
	}

	public void deleteDoctor(Integer existing) {
		Session session = getSession();

		DoctorPo doctor = (DoctorPo) getDoctors(existing);
		session.delete(doctor);
	}

	public PatientPo createPatient(String firstname, String middlename, String lastname, List<AddressPo> addresses, String personalId, String password,
			String email, List<PhonePo> phones, String salutation, InsurancePo insurancePo) throws NoSuchAlgorithmException {
		Session session = getSession();
		session.beginTransaction();

		PatientPo patient = new PatientPo();
		patient.setFirstname(firstname);
		patient.setMiddlename(middlename);
		patient.setLastname(lastname);
		patient.setNumber(personalId);
		patient.setAddress(addresses);
		patient.setEmail(email);
		patient.setSalutation(salutation);

		if (password == null)
			password = UUID.randomUUID().toString();
		patient.setPassword(generatePassword(password));

		patient.setInsurance(insurancePo);

		session.save(patient);
		session.getTransaction().commit();
		session.close();
		return patient;
	}

	@SuppressWarnings("unchecked")
	public List<PatientPo> getPatients(Integer number) {
		Session session = getSession();
		Query query;
		List<PatientPo> patientPos = new ArrayList<PatientPo>();
		if (number == null) {
			query = session.createQuery("select u from PatientPo u");
		} else {
			query = session.createQuery("select u from PatientPo u where number =  :number");
			query.setString("number", number.toString());
		}
		try{ 
			patientPos.addAll(query.list());
		} catch (ObjectNotFoundException e) {
			e.printStackTrace();
		}
		return patientPos;
	}

	public PatientPo updatePatient(Integer existing, String firstname, String lastname, String middlename, List<AddressPo> addresses, String email,
			String salutation, String personalId, Integer insuranceNumber, String password) throws NoSuchAlgorithmException {
		Session session = getSession();

		PatientPo patient = (PatientPo) getPatients(existing);

		patient.setFirstname(firstname);
		patient.setMiddlename(middlename);
		patient.setLastname(lastname);
		patient.setNumber(personalId);
		patient.setAddress(addresses);
		patient.setEmail(email);
		patient.setSalutation(salutation);

		if (password == null)
			password = UUID.randomUUID().toString();
		patient.setPassword(generatePassword(password));

		Query query = session.createQuery("FROM InsurancePo where number = :insuranceNumber");
		query.setLong("insuranceNumber", insuranceNumber);
		InsurancePo insurance = (InsurancePo) query.uniqueResult();
		patient.setInsurance(insurance);

		session.save(patient);
		session.getTransaction().commit();
		session.close();
		return patient;
	}

	public void deletePatient(Integer existing) {
		Session session = getSession();

		PatientPo patient = (PatientPo) getPatients(existing);
		session.delete(patient);
	}

	public UserPo loginToHealthCard(String number, String password) throws NoSuchAlgorithmException {
		Session session = getSession();
		Query query;

		password = generatePassword(password);

		query = session.createQuery("select u from UserPo u where number = :number and password = :password");
		query.setInteger("number", Integer.parseInt(number));
		query.setString("password", password);
		UserPo userPo = (UserPo) query.uniqueResult();
		return userPo;
	}

}
